using System;
using System.Collections;
using System.Text;

namespace Patchy
{
    /// <summary>
    /// Summary description for MinDirName.
    /// </summary>
    /// TODO: Use string-builder
    public class MinFileName
    {
        private SortedList mLookup = new SortedList(StringComparer.OrdinalIgnoreCase);
        private GroupHolder mGroupHolder;

        public MinFileName(GroupHolder groupHolder)
        {
            mGroupHolder = groupHolder;
        }

        public void Process()
        {
            ArrayList fileNames = new ArrayList();
            Hashtable uniq = new Hashtable(StringComparer.OrdinalIgnoreCase);
            foreach (MyGroup group in mGroupHolder.SortedGroupCollection)
            {
                foreach (MyFile file in group.Files)
                {
                    if (!uniq.Contains(file.NormalisedName))
                    {
                        uniq.Add(file.NormalisedName, file.NormalisedName);
                        fileNames.Add(new NameData(file.NormalisedName));
                    }
                }
            }
            fileNames.Sort();
            Shorten(fileNames, 0);
            foreach (MyGroup group in mGroupHolder.SortedGroupCollection)
            {
                foreach (MyFile file in group.Files)
                {
                    file.ShortenedName = mLookup[file.NormalisedName].ToString();
                    file.CalculateDestinedName(group.DirectoryName);
                }
            }
        }

        private void Shorten(ArrayList ar, int level)
        {
            if (ar.Count == 1)
            {
                NameData data = (NameData)ar[0];
                if (!mLookup.Contains(data.Name))
                    mLookup.Add(data.Name, data.ShortenedName(level));
                return;
            }
            else
            {
                for (int i = 1; i < ar.Count; i++)
                {
                    if (((NameData)ar[i - 1]).RSegment(level) == ((NameData)ar[i]).RSegment(level))
                    {
                        continue;
                    }
                    if (i == 1)
                        Shorten(ar.GetRange(0, i), level); //single item
                    else
                        Shorten(ar.GetRange(0, i), level + 1); //group of items
                    Shorten(ar.GetRange(i, ar.Count - i), level); //unevaluated so far
                    return;
                }
                Shorten(ar, level + 1); //whole group is a match
            }
        }
    }

    class NameData : IComparable
    {
        string mName;
        string mReversedName;
        ArrayList mSegsReversed;
        int mNumSegments;

        public NameData(string filename)
        {
            mName = filename;
            mReversedName = Reverse(mName.ToLower());
            mSegsReversed = new ArrayList(mReversedName.Split('\\'));
            mNumSegments = mSegsReversed.Count - 1;
        }

        public string RSegment(int index)
        {
            index = Math.Min(index, mNumSegments);//to stay in bounds
            return mSegsReversed[index].ToString();
        }

        public string Name
        {
            get { return mName; }
        }

        public string ShortenedName(int level)
        {
            string str = mName.Replace(":", "");
            string[] arr = str.Split('\\');
            int start = Math.Max(arr.Length - level - 1, 0);
            str = arr[start];
            for (int i = start + 1; i < arr.Length; i++)
            {
                str += '\\' + arr[i];
            }
            return str;
        }

        string Reverse(string str)
        {
            return (str.Length == 1) ? str : Reverse(str.Substring(1)) + str.Substring(0, 1);
        }

        #region IComparable Members
        public int CompareTo(object obj)
        {
            NameData d = (NameData)obj;
            return this.mReversedName.CompareTo(d.mReversedName);
        }
        #endregion
    }
}
